package com.gwm.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.gwm.common.enums.ExceptionEnums;
import com.gwm.common.exceptions.LyException;
import com.gwm.common.utils.BeanHelper;
import com.gwm.common.utils.RegexUtils;
import com.gwm.user.entity.TbUser;
import com.gwm.user.mapper.TbUserMapper;
import com.gwm.user.service.TbUserService;
import com.gwm.user.dto.UserDTO;
import org.apache.commons.lang3.RandomStringUtils;

import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.gwm.common.constants.RocketMQConstants.TAGS.VERIFY_CODE_TAGS;
import static com.gwm.common.constants.RocketMQConstants.TOPIC.SMS_TOPIC_NAME;
import static com.gwm.common.constants.SmsConstants.*;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author heima
 * @since 2020-12-01
 */
@Service
public class TbUserServiceImpl extends ServiceImpl<TbUserMapper, TbUser> implements TbUserService {

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    /**
     * 校验数据是否可用
     * @param data 用户输入的数据
     * @param type 1- 用户名  2 手机号
     * @return
     */
    public Boolean checkData(String data, Integer type) {
        QueryWrapper<TbUser> queryWrapper = new QueryWrapper<>();
        switch (type){
            case 1:
                queryWrapper.lambda().eq(TbUser::getUsername,data);
                break;
            case 2:
                queryWrapper.lambda().eq(TbUser::getPhone,data);
                break;
            default:
                throw  new LyException(ExceptionEnums.INVALID_PARAM_ERROR);
        }

        int count = this.count(queryWrapper);
        return count==1;
    }

    //redis中的key前缀
    private static final String  KEY_PREFIX = "ly:user:verify:phone:";
    @Override
    public void sendCode(String phone) {
        // 验证手机号格式
        if (!RegexUtils.isPhone(phone)) {
            throw new LyException(ExceptionEnums.INVALID_PHONE_NUMBER);
        }

        // 生成验证码
        String code = RandomStringUtils.randomNumeric(6);

        // 保存验证码到redis,有效期3分钟
        redisTemplate.opsForValue().set(KEY_PREFIX + phone, code, 1, TimeUnit.MINUTES);

        // 发送消息到ly-sms

        Map<String,String> map = new HashMap<>();
        map.put(SMS_PARAM_KEY_PHONE,phone);
        map.put(SMS_PARAM_KEY_SIGN_NAME,"黑马旅游网GWM");
        map.put(SMS_PARAM_KEY_TEMPLATE_CODE,"SMS_203716359");
        map.put(SMS_PARAM_KEY_TEMPLATE_PARAM,"{\"code\":\""+code+"\"}");
        rocketMQTemplate.convertAndSend(SMS_TOPIC_NAME+":"+VERIFY_CODE_TAGS,map);
    }

    @Override
    public void register(TbUser user, String code) {

        user.setPassword("123456");
        user.setUsername("gwm");
        user.setPhone("15132017953");
        // 1 校验验证码
        // 1.1 取出redis中的验证码
        String cacheCode = redisTemplate.opsForValue().get(KEY_PREFIX + user.getPhone());
        // 1.2 比较验证码
        if (!StringUtils.equals(code, cacheCode)) {
            throw new LyException(ExceptionEnums.INVALID_VERIFY_CODE);
        }
        // 2 对密码加密
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        // 3 写入数据库
        Boolean isSave = this.save(user);
        if (!isSave) {
            throw new LyException(ExceptionEnums.INSERT_OPERATION_FAIL);
        }
    }

    @Override
    public UserDTO queryUserByUsernameAndPassword(String username, String password) {
        QueryWrapper<TbUser> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().eq(TbUser::getUsername,username);
        TbUser tbUser = this.getOne(queryWrapper);
        if (tbUser == null) {
            // 用户名错误
            throw new LyException(ExceptionEnums.INVALID_USERNAME_PASSWORD);
        }

        // 校验密码
        if(!passwordEncoder.matches(password, tbUser.getPassword())){
            // 密码错误
            throw new LyException(ExceptionEnums.INVALID_USERNAME_PASSWORD);
        }
        return BeanHelper.copyProperties(tbUser,UserDTO.class);
    }

}
